// 커스텀 데이터 타입을 생성하는 Script 코드입니다.
// 25년 11월 기준, Script Lab 에서만 동작합니다.

// ========================================
// 📌 카테고리 설정 영역 (사용자가 편집 가능)
// ========================================
const categoryConfig = {
  //"기본 정보": ["사진","이름","사번","이메일","직급","부서","직무"],
  //"고용 정보": ["입사일","고용형태","근무지","연봉(만원)"],
  //"평가": ["평점", "리뷰수"],
  //"기타": [] // 나머지 항목 자동 등록
};
// ========================================

Office.onReady(() => {
  const btn = document.getElementById("run");
  if (btn) {
    btn.addEventListener("click", () => {
      run();
    });
  }
});

async function run() {
  try {
    await addBookEntities();
  } catch (error) {
    console.error("addBookEntities error:", error);
  }
}

async function addBookEntities() {
  await Excel.run(async (context) => {
    // 0) 현재 선택 영역에서 표 찾기
    const selection = context.workbook.getSelectedRange();
    const tablesOnSelection = selection.getTables(false);
    tablesOnSelection.load("items/name");
    await context.sync();

    if (tablesOnSelection.items.length === 0) {
      throw new Error(
        "현재 선택한 범위와 겹치는 표가 없습니다. 표 안쪽 셀을 선택한 뒤 다시 실행해 주세요."
      );
    }

    const table = tablesOnSelection.items[0];
    console.log("Target table:", table.name);

    // 1) 기존 '커스텀데이터' 컬럼이 있는지 확인
    const existingColumn = table.columns.getItemOrNullObject("커스텀데이터");
    existingColumn.load("isNullObject");
    await context.sync();

    let entityColumn;
    
    if (!existingColumn.isNullObject) {
      // 기존 컬럼이 있으면 데이터만 초기화하고 재사용
      console.log("기존 '커스텀데이터' 컬럼 발견 - 데이터를 초기화합니다.");
      entityColumn = existingColumn;
      
      // 데이터 영역만 클리어 (헤더는 유지)
      const dataBodyRange = entityColumn.getDataBodyRange();
      dataBodyRange.clear(Excel.ClearApplyTo.contents);
      await context.sync();
    } else {
      // 컬럼이 없으면 맨 앞에 새로 추가
      console.log("'커스텀데이터' 컬럼 없음 - 새로 추가합니다.");
      entityColumn = table.columns.add(0, null, "커스텀데이터");
      await context.sync();
    }

    // 2) 헤더 / 데이터 로드
    const headerRange = table.getHeaderRowRange();
    const dataRange = table.getDataBodyRange();
    headerRange.load("values");
    dataRange.load("values, numberFormat");
    await context.sync();

    const headers = headerRange.values[0] as string[];
    const rows = dataRange.values;
    const numberFormats = dataRange.numberFormat;

    console.log("headers:", headers);
    console.log("row count:", rows.length);
    if (rows.length === 0) {
      console.warn("No data rows in table.");
      return;
    }

    // 날짜 형식인지 확인하는 헬퍼 함수
    const isDateFormat = (format: string): boolean => {
      if (!format) return false;
      const datePatterns = [
        /[yYmMdD]/,  // 년월일 패턴
        /\//, // 슬래시
        /-/,  // 하이픈
      ];
      return datePatterns.some(pattern => pattern.test(format));
    };

    // 백분율 형식인지 확인하는 헬퍼 함수
    const isPercentFormat = (format: string): boolean => {
      if (!format) return false;
      return format.includes('%');
    };

    // 날짜 값을 변환하는 헬퍼 함수
    const convertExcelDate = (value: any): Date | null => {
      if (value instanceof Date) return value;
      // 30000 = 1982년 2월 18일, 60000 = 2064년 4월 8일
      if (typeof value === "number" && value > 40000 && value < 60000) {
        // 엑셀 날짜 숫자를 JavaScript Date로 변환
        const date = new Date((value - 25569) * 86400 * 1000);
        return date;
      }
      return null;
    };

    // 카테고리 설정에서 이미 정의된 필드들 수집
    const definedFields = new Set<string>();
    Object.values(categoryConfig).forEach((fields) => {
      fields.forEach((field) => definedFields.add(field));
    });

    const entities = rows.map((row, rowIndex) => {
      const properties: any = {};
      const usedFields = new Set<string>(); // 실제로 데이터가 있는 필드 추적

      // 제목으로 쓸 필드/값 결정
      let titlePropertyName: string | null = null;
      let titleText: string = "";
      let mainImageProp: string | null = null;

      // 1) 한 번 돌면서 properties 구성
      headers.forEach((header, idx) => {
        const rawValue = row[idx];

        // 빈 값 체크
        if (rawValue === null || rawValue === undefined || rawValue === "") {
          return; // 빈 값은 properties에 추가하지 않음
        }

        // 현재 셀의 numberFormat 확인
        const cellFormat = numberFormats[rowIndex][idx];
        const isDate = isDateFormat(cellFormat);
        const isPercent = isPercentFormat(cellFormat);

        const isUrl =
          typeof rawValue === "string" &&
          (rawValue.includes("http://") ||
            rawValue.includes("https://") ||
            rawValue.includes("www."));

        const numValue =
          typeof rawValue === "number" ? rawValue : Number(rawValue);
        const isNumeric = !isNaN(numValue);

        if (isUrl) {
          // URL (이미지)
          properties[header] = {
            type: "WebImage",
            address: rawValue,
          };
          if (!mainImageProp) {
            mainImageProp = header;
          }
        } else if (isDate && isNumeric) {
          // 날짜 형식 - String으로 변환하여 처리
          const dateValue = convertExcelDate(rawValue);
          if (dateValue) {
            properties[header] = {
              type: "String",
              basicValue: dateValue.toISOString().split('T')[0], // YYYY-MM-DD 형식
            };
          } else {
            properties[header] = {
              type: "String",
              basicValue: rawValue.toString(),
            };
          }
        } else if (isPercent && isNumeric) {
          // 백분율 형식 반환
          const percentValue = Math.round(numValue * 100);
          properties[header] = {
            type: "String",
            basicValue: `${percentValue}%`,
          };
        } else if (isNumeric) {
          // 일반 숫자
          properties[header] = {
            type: "Double",
            basicValue: numValue,
          };
        } else {
          // 문자열
          properties[header] = {
            type: "String",
            basicValue: rawValue.toString(),
          };
        }

        usedFields.add(header);
      });

      // 2) 카드 제목으로 사용할 필드 선택
      if (headers.includes("도서명")) {
        titlePropertyName = "도서명";
      } else {
        const titleIdx = headers.findIndex((h) =>
          h.toLowerCase().includes("title")
        );
        if (titleIdx >= 0) {
          titlePropertyName = headers[titleIdx];
        } else if (usedFields.size > 0) {
          titlePropertyName = Array.from(usedFields)[0];
        }
      }

      if (titlePropertyName && properties[titlePropertyName]) {
        titleText = properties[titlePropertyName].basicValue?.toString() || titlePropertyName;
      } else {
        titleText = row[0] != null ? row[0].toString() : "";
      }

      // 3) 카테고리별 섹션 구성
      const sections: any[] = [];

      // categoryConfig가 비어있으면 카테고리 구분 없이 모든 필드를 하나의 섹션으로
      if (Object.keys(categoryConfig).length === 0) {
        const allFields = Array.from(usedFields).filter(
          (field) => properties[field]
        );

        if (allFields.length > 0) {
          sections.push({
            layout: "List",
            properties: allFields,
          });
        }
      } else {
        // 정의된 카테고리들을 순회하며 섹션 생성
        Object.entries(categoryConfig).forEach(([categoryName, fields]) => {
          // "기타" 카테고리는 나중에 처리
          if (categoryName === "기타") return;

          // 실제로 데이터가 있는 필드만 필터링
          const existingFields = fields.filter(
            (field) => usedFields.has(field) && properties[field]
          );

          if (existingFields.length > 0) {
            sections.push({
              layout: "List",
              title: categoryName,
              properties: existingFields,
            });
          }
        });

        // 4) "기타" 카테고리 처리 - 정의되지 않은 필드들 추가
        const otherFields = Array.from(usedFields).filter(
          (field) => !definedFields.has(field) && properties[field]
        );

        if (otherFields.length > 0) {
          sections.push({
            layout: "List",
            title: "기타",
            properties: otherFields,
          });
        }
      }

      // 섹션이 실제로 있을 경우 카드 레이아웃 구성
      const cardLayout: any = {
        title: {
          property: titlePropertyName || headers[0],
        },
      };

      // 섹션이 있는 경우에만 추가
      if (sections.length > 0) {
        cardLayout.sections = sections;
      }

      // 메인 이미지가 있는 경우에만 추가
      if (mainImageProp && properties[mainImageProp]) {
        cardLayout.mainImage = { property: mainImageProp };
      }

      const entity: any = {
        type: "Entity",
        text: titleText,
        properties,
        layouts: {
          compact: { icon: "Book" },
          card: cardLayout,
        },
      };

      // 메인 이미지 설정
      if (mainImageProp && properties[mainImageProp]) {
        entity.layouts.card.mainImage = { property: mainImageProp };
      }

      return [entity];
    });

    // 5) 엔터티 값 넣기 (기존 또는 새로 추가된 컬럼에)
    entityColumn.getDataBodyRange().valuesAsJson = entities;
    await context.sync();

    console.log("커스텀 데이터 타입 생성 완료!");
  });
}